opsfull/redis/K8s上运行Redis集群指南.md at master · Lancger/opsfull · GitHub

您所在的位置:网站首页 k8s redis集群 opsfull/redis/K8s上运行Redis集群指南.md at master · Lancger/opsfull · GitHub

opsfull/redis/K8s上运行Redis集群指南.md at master · Lancger/opsfull · GitHub

2024-06-01 16:09| 来源: 网络整理| 查看: 265

Table of Contents 一、前言 二、准备操作 三、StatefulSet简介 四、部署过程 1、创建NFS存储 2、创建PV 3、创建Configmap 4、创建Headless service 4、创建Redis 集群节点 5、初始化Redis集群 6、创建用于访问Service 五、测试主从切换 六、疑问点 一、前言

架构原理:

每个Master都可以拥有多个Slave。当Master下线后,Redis集群会从多个Slave中选举出一个新的Master作为替代,而旧Master重新上线后变成新Master的Slave。

二、准备操作

本次部署主要基于该项目:

https://github.com/zuxqoj/kubernetes-redis-cluster

其包含了两种部署Redis集群的方式:

StatefulSet Service & Deployment

两种方式各有优劣,对于像Redis、Mongodb、Zookeeper等有状态的服务,使用StatefulSet是首选方式。本文将主要介绍如何使用StatefulSet进行Redis集群的部署。

三、StatefulSet简介

1、RC、Deployment、DaemonSet都是面向无状态的服务,它们所管理的Pod的IP、名字,启停顺序等都是随机的,而StatefulSet是什么?顾名思义,有状态的集合,管理所有有状态的服务,比如MySQL、MongoDB集群等。

2、StatefulSet本质上是Deployment的一种变体,在v1.9版本中已成为GA版本,它为了解决有状态服务的问题,它所管理的Pod拥有固定的Pod名称,启停顺序,在StatefulSet中,Pod名字称为网络标识(hostname),还必须要用到共享存储。

3、在Deployment中,与之对应的服务是service,而在StatefulSet中与之对应的headless service,headless service,即无头服务,与service的区别就是它没有Cluster IP,解析它的名称时将返回该Headless Service对应的全部Pod的Endpoint列表。

4、除此之外,StatefulSet在Headless Service的基础上又为StatefulSet控制的每个Pod副本创建了一个DNS域名,这个域名的格式为:

$(podname).(headless server name) FQDN: $(podname).(headless server name).namespace.svc.cluster.local

5、也即是说,对于有状态服务,我们最好使用固定的网络标识(如域名信息)来标记节点,当然这也需要应用程序的支持(如Zookeeper就支持在配置文件中写入主机域名)。

6、StatefulSet基于Headless Service(即没有Cluster IP的Service)为Pod实现了稳定的网络标志(包括Pod的hostname和DNS Records),在Pod重新调度后也保持不变。同时,结合PV/PVC,StatefulSet可以实现稳定的持久化存储,就算Pod重新调度后,还是能访问到原先的持久化数据。

7、以下为使用StatefulSet部署Redis的架构,无论是Master还是Slave,都作为StatefulSet的一个副本,并且数据通过PV进行持久化,对外暴露为一个Service,接受客户端请求。

四、部署过程 1.创建NFS存储 2.创建PV 3.创建PVC 4.创建Configmap 5.创建headless服务 6.创建Redis StatefulSet 7.初始化Redis集群 1、创建NFS存储

创建NFS存储主要是为了给Redis提供稳定的后端存储,当Redis的Pod重启或迁移后,依然能获得原先的数据。这里,我们先要创建NFS,然后通过使用PV为Redis挂载一个远程的NFS路径。

yum -y install nfs-utils #主包提供文件系统 yum -y install rpcbind #提供rpc协议

然后,新增/etc/exports文件,用于设置需要共享的路径

$ cat /etc/exports /data/nfs/redis/pv1 *(rw,no_root_squash,sync,insecure) /data/nfs/redis/pv2 *(rw,no_root_squash,sync,insecure) /data/nfs/redis/pv3 *(rw,no_root_squash,sync,insecure) /data/nfs/redis/pv4 *(rw,no_root_squash,sync,insecure) /data/nfs/redis/pv5 *(rw,no_root_squash,sync,insecure) /data/nfs/redis/pv6 *(rw,no_root_squash,sync,insecure) #创建相应目录 mkdir -p /data/nfs/redis/pv{1..6} #接着,启动NFS和rpcbind服务 systemctl restart rpcbind systemctl restart nfs systemctl enable nfs systemctl enable rpcbind #查看 exportfs -v #客户端 yum -y install nfs-utils #查看存储端共享 showmount -e localhost 2、创建PV

每一个Redis Pod都需要一个独立的PV来存储自己的数据,因此可以创建一个pv.yaml文件,包含6个PV

kubectl delete -f pv.yaml cat >pv.yaml#配置文件redis.conf cat >redis.conf#删除svc kubectl delete -f headless-service.yaml #编写svc cat >headless-service.yamlredis.yaml# kubectl get pods -o wide NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE redis-app-0 1/1 Running 0 2h 172.17.24.3 192.168.0.144 redis-app-1 1/1 Running 0 2h 172.17.63.8 192.168.0.148 redis-app-2 1/1 Running 0 2h 172.17.24.8 192.168.0.144 redis-app-3 1/1 Running 0 2h 172.17.63.9 192.168.0.148 redis-app-4 1/1 Running 0 2h 172.17.24.9 192.168.0.144 redis-app-5 1/1 ContainerCreating 0 2h 172.17.63.10 192.168.0.148 如上,可以看到这些Pods在部署时是以{0…N-1}的顺序依次创建的。注意,直到redis-app-0状态启动后达到Running状态之后,redis-app-1 才开始启动。 同时,每个Pod都会得到集群内的一个DNS域名,格式为$(podname).$(service name).$(namespace).svc.cluster.local ,也即是: redis-app-0.redis-service.default.svc.cluster.local redis-app-1.redis-service.default.svc.cluster.local ...以此类推... 这里我们可以验证一下 #kubectl run --rm curl --image=radial/busyboxplus:curl -it kubectl run --rm -i --tty busybox --image=busybox:1.28 /bin/sh $ nslookup redis-app-0.redis-service #注意格式 $(podname).$(service name).$(namespace) Server: 10.96.0.10 Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local Name: redis-app-0.redis-service Address 1: 172.17.24.3 redis-app-0.redis-service.default.svc.cluster.local 在K8S集群内部,这些Pod就可以利用该域名互相通信。我们可以使用busybox镜像的nslookup检验这些域名(一条命令) $ kubectl run -it --rm --image=busybox:1.28 --restart=Never busybox -- nslookup redis-app-0.redis-service Server: 10.96.0.10 Address 1: 10.96.0.10 kube-dns.kube-system.svc.cluster.local Name: redis-app-0.redis-service Address 1: 172.17.24.3 redis-app-0.redis-service.default.svc.cluster.local pod "busybox" deleted 可以看到, redis-app-0 的IP为172.17.24.3。当然,若Redis Pod迁移或是重启(我们可以手动删除掉一个Redis Pod来测试),IP是会改变的,但是Pod的域名、SRV records、A record都不会改变。 另外可以发现,我们之前创建的pv都被成功绑定了: $ kubectl get pv|grep nfs-pv nfs-pv1 20Gi RWX Retain Bound default/redis-data-redis-app-1 nfs 65s nfs-pv2 20Gi RWX Retain Bound default/redis-data-redis-app-0 nfs 65s nfs-pv3 20Gi RWX Retain Bound default/redis-data-redis-app-2 nfs 65s nfs-pv4 20Gi RWX Retain Bound default/redis-data-redis-app-5 nfs 65s nfs-pv5 20Gi RWX Retain Bound default/redis-data-redis-app-3 nfs 65s nfs-pv6 20Gi RWX Retain Bound default/redis-data-redis-app-4 nfs 65s 查看pvc资源 $ kubectl get pvc NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE redis-data-redis-app-0 Bound nfs-pv2 20Gi RWX nfs 96s redis-data-redis-app-1 Bound nfs-pv1 20Gi RWX nfs 86s redis-data-redis-app-2 Bound nfs-pv3 20Gi RWX nfs 75s redis-data-redis-app-3 Bound nfs-pv5 20Gi RWX nfs 69s redis-data-redis-app-4 Bound nfs-pv6 20Gi RWX nfs 62s redis-data-redis-app-5 Bound nfs-pv4 20Gi RWX nfs 56s 5、初始化Redis集群

创建好6个Redis Pod后,我们还需要利用常用的Redis-tribe工具进行集群的初始化

创建Ubuntu容器

由于Redis集群必须在所有节点启动后才能进行初始化,而如果将初始化逻辑写入Statefulset中,则是一件非常复杂而且低效的行为。这里,本人不得不称赞一下原项目作者的思路,值得学习。也就是说,我们可以在K8S上创建一个额外的容器,专门用于进行K8S集群内部某些服务的管理控制。 这里,我们专门启动一个Ubuntu的容器,可以在该容器中安装Redis-tribe,进而初始化Redis集群,执行:

1、#创建一个ubuntu容器 kubectl run -it ubuntu --image=ubuntu --restart=Never /bin/bash #进入到容器 kubectl exec -it ubuntu /bin/bash 2、#我们使用阿里云的Ubuntu源,执行 $ cat > /etc/apt/sources.list cluster info cluster_state:ok cluster_slots_assigned:16384 cluster_slots_ok:16384 cluster_slots_pfail:0 cluster_slots_fail:0 cluster_known_nodes:6 cluster_size:3 cluster_current_epoch:6 cluster_my_epoch:6 cluster_stats_messages_ping_sent:14910 cluster_stats_messages_pong_sent:15139 cluster_stats_messages_sent:30049 cluster_stats_messages_ping_received:15139 cluster_stats_messages_pong_received:14910 cluster_stats_messages_received:30049 127.0.0.1:6379> 另外,还可以在NFS上查看Redis挂载的数据: $ ll /data/nfs/redis/pv3 total 12 -rw-r--r-- 1 root root 92 Jun 4 11:36 appendonly.aof -rw-r--r-- 1 root root 175 Jun 4 11:36 dump.rdb -rw-r--r-- 1 root root 794 Jun 4 11:49 nodes.conf 6、创建用于访问Service

前面我们创建了用于实现StatefulSet的Headless Service,但该Service没有Cluster Ip,因此不能用于外界访问。所以,我们还需要创建一个Service,专用于为Redis集群提供访问和负载均衡:

#删除服务 kubectl delete -f redis-access-service.yaml #编写yaml cat >redis-access-service.yaml


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3